<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\ResponseException;
use App\Http\Requests\Api\Order\OrderPayRequest;
use App\Jobs\OrderPayEmailNotify;
use App\Models\Order;
use App\Models\OrderInfo;
use App\Models\User;
use Illuminate\Http\Request;
use Yansongda\Pay\Exceptions\GatewayException;
use Yansongda\Pay\Exceptions\InvalidConfigException;
use Yansongda\Pay\Exceptions\InvalidGatewayException;
use Yansongda\Pay\Exceptions\InvalidSignException;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Log;
use App\Http\Controllers\Controller;

class AlipayController extends Controller
{
	protected $config = [
		'app_id' => '2016092100564151',

		'notify_url' => 'http://lv.17hxg.com/api/alipay/orderPayNotify',

		'return_url' => 'http://lv.17hxg.com/api/alipay/orderPayReturn',

		'ali_public_key' => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqWf1fuWNXqDnf4Fpq/f1BxJvj/hpLRvvzlsqqWqG/RYxKoNJv6JvcapkBVGIjwe50a67ICO37RapJ1qysNSSPX533iXgyqSwKysmjVQYAOsjXnApUBtrXzdeBbl9+sNp1u2Lb4OXR8PDLLwN7zp0kzEkAtfAdWdTW/n6qLxAkywmF7Jede7BOOi5Eoetxh/0Hx7zRIZGDZVp8rrXm26T/PmKUT0G8flGRSUnC7JYeDdJj98l3uL7uT4wk6aQyfYNpqWoolyjHxKUYjMdnWDAd9kl7TJOwL7RqoDSl0x9egf1pMKnJtKmmbyZU+snMgHTTzQe3JVJV24ALvdGIUViFwIDAQAB',

		// 加密方式： **RSA2**
		'private_key' => 'MIIEowIBAAKCAQEAx8chdNL73FxNgfbQjX24YNdTIJzvAvljbawQTmPNcP3vgxWx/Z3g1CZ5Wv8GUVXtp8cqan1uwp9umm1jUrluAoELINbSRZow8Kdad22+4l1ld9XBMIGsSn5IeCB5X3hofw8aqO6rgU2sW7dX7BQqkZKf2RlYe/fCiW13WFpBcxsuB0TUwX3NKGxJiLJ8WLIiXAVprLY/ZJ6s9VVCHziZJ7md1NVCdmwDm/IPYVHnGxr14wcEY1vkByGVK8wvNV2xC/GrdpFeoHY087rByCzCcwTXSyK4AiwDwv7ARBNkKq9xdmT90+9CH1/Ut7RvyLrbH6jYleDgauV7to2l2Na2UwIDAQABAoIBAQCF9u9lcpG33CGRdBu3tcVtExdIOFRCT0+wXIB2wJAkI/R3l5XKtxLr0HzyWy82XYPHTVQRItmiIt09Kvs+nt+5SCVZORS53cLRrbeJfItTKkP/jtREncAWGAaqn0QklA6mnU9IVvuk8pwQyKppwcAl7AfKwidGwgautzwfgC6Ba1oZ8ZLW+JEde/kwYL5X5IDVzWk/bjXSX3KRkY6vTcZ1itNvsgPRtMIRnUMp+szmDjzdXOYmsC8hgGc/uYi6/fj0dXQszsHTlVwWFqwqJyY5fMYnWbCAN+Nlro97vYypML/nMSS3V8zMCbg5NwwRKYiqqVduIMlJY0tclpe2uKOxAoGBAOdksJBO+CteA85N0x2piC82els0nw2dRVxms7mgxWceO4AVKvPEjtkPGulzxJvX6kefC3w64oFpdpbKHILIiZiJ6D5jn2spwsQ5pEC6nJuyqewcSHA6KWBi1opSKJziNibI2Tw6yvQdY1nsic4KRA0pT1IAw3+oOwu8iDkSYPupAoGBAN0FwsnmRC33yq85QOcczQKlTksoLYhZcvmatLVQV0JaA0BRdibCQ6rvdAod9aQ4S9aYge8FmMRA/eNAvXuAhPdvkA9ou7P9him6DeqSV0EkQ10ZkXvXdNrnZqTsx3I/lQff9/Q6XmAUFoRLfnvhBX/lzlx2q8dCdKGqkNTwif+bAoGAZageycdnz+Wl1mTqcwWgBt3wM1GS7vBBIK8eFldDYmIt0b96901LVKEGObnajnz1ODHvYcyc5i3nI6f3jp17lcBAf+hUiUf3gS2xs55IXz7G2Cw0xtlGhEnn5yzhGstm7vMePQ+3Sjf/BeqdQB/SddXIO0aKnPLTvfw9/JTOdsECgYBilZ88zyi6GDyfy7nXXFFVTMaPX2xv1PYjv427EgrZ3ax1k+BPiXcFV6k6mgJnLXUmUwAhzS1G3HZiVw4teDXW6Dwpo12V+w9MrWBnsL6an8IsVKs/weqteWmfRr3vh8zBpnTCywYtdMhWWhYgy03YrnhNZeFZD5tWQO45DNGA4QKBgGz6sFkdUcyKUceShwzev5ab/qdtey2XD+rrIKHxiSA7Vxk6b54SChFoLsWerpFhof4VxG4Gm/mDZmtRUGayXYAfqMmBWAv9oF7y3+lGJgU7y5iFcxBUKb+Hqk3TiwGDytf/NqWJfX5BUE6JFQK5XSGunPMg5EaPFwvuSmjYjDGH',

		'log' => [ // optional
			'file' => '/www/wwwroot/lv.17hxg.com/logs/alipay.log',
			'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
			'type' => 'single', // optional, 可选 daily.
			'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
		],
		'http' => [ // optional
			'timeout' => 5.0,
			'connect_timeout' => 5.0,
			// 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
		],
		'mode' => 'dev', // optional,设置此参数，将进入沙箱模式
	];

	/**
	 * 订单支付
	 * User: Clannad ~ ☆
	 * DataTime：2019/11/23 0023 10:00
	 * @return \Symfony\Component\HttpFoundation\Response
	 */
	public function orderPay(OrderPayRequest $request)
	{
		//获得支付宝的配置参数
		$config = config('alipay.pay_param');

		$order_sn = $request->input('order_sn');

		$order = Order::query()
			->select('order_sn','id','price_total','goods_total')
			->where([
				'order_sn'=>$order_sn,
//				'user_id'=>auth('api')->id(),
		])->first();

		if(!$order){
		    throw new ResponseException(404,'订单不存在');
		}

		//取订单详情表的第一条，用于显示付款的商品名称
		$order_info = OrderInfo::query()
					->select('goods_name')
					->where([
						'order_sn'=>$order_sn,
						'order_id'=>$order['id'],
					])->first();

		$pay_order = [
			'body'=>config('alipay.body'),//订单头部描述商城名称
			'out_trade_no' => $order_sn,//订单号
			'total_amount' => $order['price_total'],//总金额
			'subject' => $order['goods_total'] > 1 ? $order_info['goods_name'] . '等多件商品' : $order_info['goods_name'],//商品名称
		];

		$alipay = Pay::alipay($config)->web($pay_order);
		$form = $alipay->getContent();

		throw new ResponseException(200,'ok',$form);
//		return $alipay;
	}


	/**
	 * 同步回调后的请求接口
	 * User: Clannad ~ ☆
	 * DataTime：2019/11/23 0023 15:23
	 * @throws \Yansongda\Pay\Exceptions\InvalidConfigException
	 * @throws \Yansongda\Pay\Exceptions\InvalidSignException
	 */
	public function orderPayReturn(Request $request)
	{
		//由同步回调的前端发送给后端
		$returnData = [
			'charset'      => $request->input('charset'),
			'out_trade_no' => $request->input('out_trade_no'),
			'method'       => $request->input('method'),
			'total_amount' => $request->input('total_amount'),
			'sign'         => $request->input('sign'),
			'trade_no'     => $request->input('trade_no'),
			'auth_app_id'  => $request->input('auth_app_id'),
			'version'      => $request->input('version'),
			'app_id'       => $request->input('app_id'),
			'sign_type'    => $request->input('sign_type'),
			'seller_id'    => $request->input('seller_id'),
			'timestamp'    => $request->input('timestamp'),
		];

		try{
			$data = Pay::alipay(config('alipay.pay_param'))->verify($returnData); // 是的，验签就这么简单！

			//到后台查订单
			$order = Order::query()->where([
				'order_sn'=>$data->out_trade_no,
//				'user_id'=>auth('api')->id(),
			])->first();

			if(!$order){
			    throw new ResponseException(404,'订单不存在');
			}

			//校验金额
			if(!bccompNum($data->total_amount,'=',$order['price_total'])){
			    throw new ResponseException(422,'订单金额校验异常');
			}

			if(!$order['status'] == 1 && !$order['pay_time']){
				throw new ResponseException(422,'订单处理中，请稍后前往我的订单查看处理结果');
			}else{
				throw new ResponseException(200,'支付成功');
			}

		}catch (InvalidSignException $e){
			throw new ResponseException(422,'数据签名校验错误');
		}catch (InvalidGatewayException $e){
			throw new ResponseException(422,'网关错误');
		}catch (InvalidConfigException $e){
			throw new ResponseException(422,'参数错误');
		}catch(GatewayException $e){
			throw new ResponseException(422,'返回数据异常');
		}
		// 订单号：$data->out_trade_no
		// 支付宝交易号：$data->trade_no
		// 订单总金额：$data->total_amount
	}

	/**
	 * 订单支付接口
	 * User: Clannad ~ ☆
	 * DataTime：2019/11/23 0023 16:42
	 * @return string|\Symfony\Component\HttpFoundation\Response|void
	 */
	public function orderPayNotify()
	{
		$config = config('alipay.pay_param');

		$alipay = Pay::alipay($config);

		try{
			$data = $alipay->verify(); // 是的，验签就这么简单！

			// 请自行对 trade_status 进行判断及其它逻辑进行判断，在支付宝的业务通知中，只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时，支付宝才会认定为买家付款成功。
			// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号；
			// 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）；
			// 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）；
			// 4、验证app_id是否为该商户本身。
			// 5、其它业务逻辑情况

			//验证APP_ID是否和配置的一致
			if($data->app_id != $config['app_id']){
				return;
			}

			//获取支付宝的通知返回参数，可参考技术文档中服务器异步通知参数列表

			// 如果订单状态不是成功或者结束，则不走后续的逻辑
			// 所有交易状态：https://docs.open.alipay.com/59/103672
			if(!in_array($data->trade_status, ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
				return $alipay->success();
			}

			$order = Order::query()->where('order_sn',$data->out_trade_no)->first();

			if(!$order){
				return 'fail';
			}

			//判断支付状态 支付过的不走流程
			if($order['status'] == 2 && $order['pay_time']){
				return $alipay->success();
			}

			//校验金额
			if(!bccompNum($order['price_total'],'=',$data->total_amount)){
				return;
			}

			//更新订单
			$order->status = 1;
			$order->pay_time = $data->gmt_payment;
			$order->pay_type = 1; //支付宝支付 1
			$order->trade_no = $data->trade_no;
			$order->save();

			//查询订单用户
			$user = User::select('email','nick_name')->find($order->user_id);
			//通知队列，支付成功
			dispatch(new OrderPayEmailNotify($user->email,$user->nick_name,$data->out_trade_no));

			Log::debug('Alipay notify', $data->all());
		} catch (\Exception $e) {
			// $e->getMessage();
			Log::info('Alipay notify', $data->all());
			return 'fail';
		}

		return $alipay->success();// laravel 框架中请直接 `return $alipay->success()`
	}
}
